10 #define forn(i,n) for(int i = 0; i < n; ++i)
11 #define forsn(i,s,n) for(int i = (s); i < (n); i++)
12 #define foreachin(it,s) for(__typeof__((s).begin()) it = ((s).begin()); it != ((s).end()); ++it)
14 #define inverso_de_73_mod_137 122
15 #define inverso_de_137_mod_73 8
16 #define coef_137 1096 // 137*8
17 #define coef_73 8906 // 73*122
19 static int cuad73
[73];
20 static int cuad137
[137];
22 #define resto(x,y) ((((x) % (y)) + (y)) % (y))
24 // si (a,b) = 1, deja en x el inverso multiplicativo de a ,mod b
25 // basicamente es la idea del algoritmo de euclides, pero iterativo
26 // mas info: www.math.hawaii.edu/~lee/discrete/combination.ps
27 void combinacion(int a
, int b
, int&x
) {
34 while (g0
% g1
!= 0) {
35 //invariante: a*x_1+b*y_1=g1
52 /* utiliza la ecuacion: a^2*x +a*b+b \equiv y
53 * para despejar b, si no es posible, es porque el a no era correcto
54 * b*(a+1) \equiv y -a^2
56 bool obtener_b(int a
, int x
, int y
,int& b
) {
57 if ((a
+1) % 73 == 0) {
58 // para poder encontrar un b, la parte derecha tb tiene que ser congruente a 0 modulo 73
59 if (y
-resto(a
*a
,73)*x
%73 != 0)return false;
61 combinacion((a
+1),137,amas1inv
);
62 amas1inv
= resto(amas1inv
,137);
65 aux
= resto((y
- acuad
*x
),137);
71 // para poder encontrar un b, la parte derecha tb tiene que ser congruente a 0 modulo 137
72 if (y
-resto(a
*a
,137)*x
%137 != 0)return false;
74 combinacion((a
+1),73,amas1inv
);
75 amas1inv
= resto(amas1inv
,73);
78 aux
= resto((y
- acuad
*x
),73);
84 combinacion((a
+1),137,amas1inv137
);
85 amas1inv137
= resto(amas1inv137
,137);
86 int acuad137
= a
*a
% 137;
87 int aux137
= resto((y
- acuad137
*x
),137);
88 int b137
= aux137
*amas1inv137
% 137;
90 combinacion((a
+1),73,amas1inv73
);
91 amas1inv73
= resto(amas1inv73
,73);
92 int acuad73
= a
*a
%73;
93 int aux73
= resto((y
- acuad73
*x
),73);
94 int b73
= aux73
*amas1inv73
%73;
96 //usamos teorema chino del resto, para encontrar b
98 b
= ((b73
*coef_137
)+(b137
*coef_73
)) % 10001;
104 static int numeros
[101];
106 bool testear_candidato(int a
, int b
, int cant
,list
<int>& res
) {
108 int f
= (a
*numeros
[i
]+b
)% 10001;
110 if (numeros
[i
+1] < cant
&& (a
*f
+b
)% 10001 != numeros
[i
+1]) {
114 return res
.size() == cant
;
117 void llenar_res(int a
,int a1
,int x
, int y
,int cant
,list
<int>& res
,int q
) {
119 int candidatos
[2] = {a
,a1
};
122 if (obtener_b(candidatos
[t
],x
,y
,b
)) {
123 if (testear_candidato(candidatos
[t
],b
,cant
,res
))break;
128 candidatos
[0]=candidatos
[0]+q
;
129 candidatos
[1]=candidatos
[1]+q
;
135 void resolver(const int cuadk
[],int k
,int x
,int y
,int qk
, int wk
,int cant
) {
138 combinacion(qk
,k
,qkinv
);
139 qkinv
= resto(qkinv
,k
);
140 int acuad
= (wk
*qkinv
)%k
;
145 llenar_res(a
,a1
,x
,y
,cant
,res
,k
);
152 int main(int argc
, char** argv
) {
153 // cuad73[k] = a / a^2 % 73 == k
154 // notar que alcanza mirar hasta 37 (73/2+1)
155 // porque j^2 % 73 == (73 - j)^2
156 // ademas no hay a1,a2 entre [0,73/2+1) tal que a1^2 % 73 == a2^2 % 73
158 cuad73
[(each
*each
)%73] = each
;
161 // simil a lo anterior
163 cuad137
[(each
*each
)%137]=each
;
170 scanf("%d",&numeros
[i
]);
175 printf("%d\n",numeros
[cant
-1]);
193 a^2(x-y) \equiv (y-z)
195 Resolver esa ecuacion modulo 137 y 73 y obtener candidatos para a.
196 obtener un b para alguno de los candidatos. usar esa pareja (a,b)
201 int q137
= resto(q
,137);
202 int q73
= resto(q
,73);
203 int w137
= resto(w
,137);
204 int w73
= resto(w
,73);
208 printf("%d\n",numeros
[cant
-1]);
212 resolver(cuad73
,73,x
,y
,q73
,w73
,cant
);
217 resolver(cuad137
,137,x
,y
,q137
,w137
,cant
);
222 combinacion(q137
,137,q137inv
);
223 q137inv
= resto(q137inv
,137);
224 int acuad137
= (w137
*q137inv
)%137;
225 combinacion(q73
,73,q73inv
);
226 q73inv
= resto(q73inv
,73);
227 int acuad73
= (w73
*q73inv
)%73;
229 int j
= cuad73
[acuad73
];
230 int k
= cuad137
[acuad137
];
232 int candidatos
[4] = { resto(j
*coef_137
+ k
* coef_73
,10001), resto((73-j
)*coef_137
+ k
* coef_73
,10001),
233 resto((73-j
)*coef_137
+ (137-k
)* coef_73
,10001), resto(j
*coef_137
+ (137-k
)* coef_73
,10001)
237 if (obtener_b(a
,x
,y
,b
)) {
238 if (testear_candidato(a
,b
,cant
,res
)) {
252 if (scanf("%d\n",&cant
)!=1)break;
254 return (EXIT_SUCCESS
);